﻿/*--------------------------------------------------------------------------------
 * Adaptive Intelligence - Windows Forms Controls Class Library
 * Version 2.00
 * 
 * Toolbox Title Control Base Class
 *      Provides a base definition for toolbox controls which show a title.
 *------------------------------------------------------------------------------*/

/*--------------------------------------------------------------------------------
 * System Imports
 *------------------------------------------------------------------------------*/
using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Adaptive.Foundation.Windows.Forms
{
    /// <summary>
    /// Provides a base definition for toolbox controls which show a title.
    /// </summary>
    public partial class TooboxTitleControlBase : AdaptiveControlBase
    {
        /*--------------------------------------------------------------------------------
         * Public Event Definitions
         *------------------------------------------------------------------------------*/
        #region Public Event Definitions
        /// <summary>
        /// Occurs when the item is right-clicked.
        /// </summary>
        public event EventHandler RightClick;
        #endregion

        /*--------------------------------------------------------------------------------
         * Private Member Declarations
         *------------------------------------------------------------------------------*/
        #region Private Member Declarations
        /// <summary>
        /// Brush for drawing the top section.
        /// </summary>
        private LinearGradientBrush _startBrush;
        /// <summary>
        /// Brush for drawing the bottom section.
        /// </summary>
        private LinearGradientBrush _endBrush;
        /// <summary>
        /// Brush for the text to be drawn.
        /// </summary>
        private SolidBrush _textBrush;
        /// <summary>
        /// Text shadow brush.
        /// </summary>
        private SolidBrush _shadowBrushA;
        /// <summary>
        /// Text shadow brush.
        /// </summary>
        private SolidBrush _shadowBrushB;
        /// <summary>
        /// Starting color for the title bar on the top and bottom.
        /// </summary>
        private Color _startColor;
        /// <summary>
        /// Ending, or middle color for the title bar.
        /// </summary>
        private Color _midColor;
        /// <summary>
        /// Text anti-aliasing flag.
        /// </summary>
        private bool _antiAlias;
        /// <summary>
        /// Text shadowing flag.
        /// </summary>
        private bool _shadowText;
        /// <summary>
        /// Offset position for text start.
        /// </summary>
        private Point _textOffset;
        #endregion

        /*--------------------------------------------------------------------------------
         * Constructor / Dispose / Destructor Methods
         *------------------------------------------------------------------------------*/
        #region Constructor / Dispose / Destructor Methods
        /// <summary>
        /// Initializes a new instance of the class.
        /// </summary>
        /// <remarks>
        /// This is the default constructor.
        /// </remarks>
        public TooboxTitleControlBase()
            : base()
        {
            _textOffset = new Point(0, 0);
            InitializeComponent();

            SetStyle(ControlStyles.AllPaintingInWmPaint, true);
            SetStyle(ControlStyles.ContainerControl, false);
            SetStyle(ControlStyles.Opaque, false);
            SetStyle(ControlStyles.OptimizedDoubleBuffer, true);
            SetStyle(ControlStyles.ResizeRedraw, true);
            SetStyle(ControlStyles.Selectable, false);
            SetStyle(ControlStyles.SupportsTransparentBackColor, true);
            SetStyle(ControlStyles.UserPaint, true);

            SetColors();
            
        }
        /// <summary>
        /// Deallocates internally allocated objects.
        /// </summary>
        /// <param name="disposing">
        /// A value indicating whether the object is being disposed.
        /// </param>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (_startBrush != null)
                    _startBrush.Dispose();
                if (_endBrush != null)
                    _endBrush.Dispose();
                if (_textBrush != null)
                    _textBrush.Dispose();

                if (components != null)
                    components.Dispose();
            }

            _startBrush = null;
            _endBrush = null;
            _textBrush = null;
            components = null;
            base.Dispose(disposing);
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Public Properties
         *------------------------------------------------------------------------------*/
        #region Public Properties
        /// <summary>
        /// Gets or sets a value indicating whether to anti-alias the text.
        /// </summary>
        /// <value><c>true</c> if anti-aliasing is used; otherwise, <c>false</c>.</value>
        public bool AntiAlias
        {
            get
            {
                return _antiAlias;
            }
            set
            {
                if (value != _antiAlias)
                {
                    _antiAlias = value;
                    Invalidate();
                }
            }
        }
        /// <summary>
        /// Gets or sets the foreground color of the control.
        /// </summary>
        /// <value></value>
        /// <returns>The foreground <see cref="T:System.Drawing.Color"/> of the control. The default is the value of the <see cref="P:System.Windows.Forms.Control.DefaultForeColor"/> property.</returns>
        /// <PermissionSet>
        /// 	<IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Unrestricted="true"/>
        /// </PermissionSet>
        public override Color ForeColor
        {
            get
            {
                return base.ForeColor;
            }
            set
            {
                base.ForeColor = value;
                SetColors();
                Invalidate();
            }
        }
        /// <summary>
        /// Gets or sets the start color for the title bar gradient.
        /// </summary>
        /// <value>The gradient (top and bottom) starting color.</value>
        public Color StartColor
        {
            get
            {
                return _startColor;
            }
            set
            {
                if (value != _startColor)
                {
                    _startColor = value;
                    SetColors();
                    Invalidate();
                }
            }
        }
        /// <summary>
        /// Gets or sets the mid-section color for the title bar gradient.
        /// </summary>
        /// <value>The gradient ending color for the center of the title bar.</value>
        public Color MidColor
        {
            get
            {
                return _midColor;
            }
            set
            {
                if (value != _midColor)
                {
                    _midColor = value;
                    SetColors();
                    Invalidate();
                }
            }
        }
        /// <summary>
        /// Gets or sets a value indicating whether to show a shadow under the text.
        /// </summary>
        /// <value><c>true</c> if a text shadow is to be drawn; otherwise, <c>false</c>.</value>
        public bool ShadowText
        {
            get
            {
                return _shadowText;
            }
            set
            {
                if (value != _shadowText)
                {
                    _shadowText = value;
                    if (_shadowBrushA != null)
                        _shadowBrushA.Dispose();
                    if (_shadowBrushB != null)
                        _shadowBrushB.Dispose();

                    if (_shadowText)
                    {
                        Color shadowA = LightenColor(_midColor, -20, 200);
                        Color shadowB = LightenColor(_midColor, -40, 220);

                        _shadowBrushA = new SolidBrush(shadowA);
                        _shadowBrushB = new SolidBrush(shadowB);
                    }
                    
                    SetColors();
                    Invalidate();
                }
            }
        }
        /// <summary>
        /// Gets or sets the text of the control.
        /// </summary>
        /// <value>
        /// The text associated with this control.
        /// </value>
        [Browsable(true), DefaultValue(""), Description("Text to be displayed."),
         DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
        public override string Text
        {
            get
            {
                return base.Text;
            }
            set
            {
                if (value != base.Text)
                {
                    base.Text = value;
                    Invalidate();
                }
            }
        }
        /// <summary>
        /// Gets the text offset.
        /// </summary>
        /// <value>The text offset.</value>
        public Point TextOffset
        {
            get { return _textOffset; }
            set
            {
                _textOffset = value;
                Invalidate();
            }
        }
        #endregion

        /*--------------------------------------------------------------------------------
         * Protected Methods / Event Methods
         *------------------------------------------------------------------------------*/
        #region Protected Methods / Event Methods
        /// <summary>
        /// Sets the colors and creates the neccessary brushes.
        /// </summary>
        protected virtual void SetColors()
        {
            if (_startBrush != null)
                _startBrush.Dispose();
            if (_endBrush != null)
                _endBrush.Dispose();
            if (_textBrush != null)
                _textBrush.Dispose();

            if (Width == 0)
                Width = 1;

            try
            {
                _startBrush = new LinearGradientBrush(new Rectangle(0, 0, Width, (int)(((float)Height) / 2)),
                                        _startColor, _midColor, LinearGradientMode.Vertical);
            }
            catch
            {
                _startBrush = null;
            }

            try
            {
                _endBrush = new LinearGradientBrush(new Rectangle(0, (int)((float)Height / 2) - 2, Width, (int)((float)Height / 2) + 2),
                                        _midColor, _startColor, LinearGradientMode.Vertical);
            }
            catch
            {
                _endBrush = null;
            }

            try
            {
                _textBrush = new SolidBrush(ForeColor);
            }
            catch
            {
                _textBrush = null;
            }
        }
        /// <summary>
        /// Translates the mouse down event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.MouseEventArgs"/> that contains the event data.</param>
        protected override void OnMouseDown(System.Windows.Forms.MouseEventArgs e)
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Right)
                OnRightClick(EventArgs.Empty);
            else
                base.OnMouseDown(e);
        }
        /// <summary>
        /// Paints the background of the control.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
        protected override void OnPaintBackground(PaintEventArgs e)
        {
            base.OnPaintBackground(e);

            int midPoint = 0;

            if ((Visible) && (Created))
            {
                midPoint = (int)((float)Height / 2) + 2;

                if (_startBrush != null)
                    e.Graphics.FillRectangle(_startBrush, new Rectangle(0, 0, Width, midPoint-1));
                if (_endBrush != null)
                    e.Graphics.FillRectangle(_endBrush, new Rectangle(0, midPoint - 2, Width, midPoint + 2));

            }
        }
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.Resize"/> event.
        /// </summary>
        /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
        protected override void OnResize(System.EventArgs e)
        {
            base.OnResize(e);
            //SetColors();
            Invalidate();
            Refresh();
        }
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Forms.Control.Paint"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.Forms.PaintEventArgs"/> that contains the event data.</param>
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);

            if ((Visible) && (Created))
            {
                e.Graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
                e.Graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
                e.Graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;

                if (_antiAlias)
                    e.Graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

                if ((_shadowText)&& (_shadowBrushB != null) && (_shadowBrushA != null))
                {
                    e.Graphics.DrawString(base.Text, Font, _shadowBrushB, _textOffset.X + 2, _textOffset.Y + 2);
                    e.Graphics.DrawString(base.Text, Font, _shadowBrushA, _textOffset.X + 1, _textOffset.Y + 1);
                }
                
                if (_textBrush != null)
                    e.Graphics.DrawString(base.Text, Font, _textBrush, _textOffset);
            }
        }
        /// <summary>
        /// Raises the <see cref="E:RightClick"/> event.
        /// </summary>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        protected virtual void OnRightClick(EventArgs e)
        {
            if (RightClick != null)
                RightClick(this, e);
        }
        /// <summary>
        /// Creates a "lighter" version of the specified color value.
        /// </summary>
        /// <param name="originalValue">
        /// A red, green, or blue color value.
        /// </param>
        /// <param name="value">
        /// The value to modify the color by.
        /// </param>
        /// <returns>
        /// The lightened value to a maximum value of 255.
        /// </returns>
        protected int LightenValue(int originalValue, int value)
        {
            originalValue += value;
            if (originalValue > 255)
                originalValue = 255;
            if (originalValue < 0)
                originalValue = 0;
            
            return originalValue;
        }
        /// <summary>
        /// Creates a "lighter" version of the specified color.
        /// </summary>
        /// <param name="original">
        /// The color value to be lightened.
        /// </param>
        /// <param name="value">
        /// The value to modify the color by.
        /// </param>
        /// <returns>
        /// A new <see cref="Color"/> value.
        /// </returns>
        protected Color LightenColor(Color original, int value)
        {
            Color returnValue;

            returnValue = Color.FromArgb(255, LightenValue(original.R, value),
                                              LightenValue(original.G, value),
                                              LightenValue(original.B, value));

            return returnValue;
        }
        /// <summary>
        /// Creates a "lighter" version of the specified color.
        /// </summary>
        /// <param name="original">
        /// The color value to be lightened.
        /// </param>
        /// <param name="opacity"> The new opacity value.
        /// </param>
        /// <param name="value">
        /// The value to modify the color by.
        /// </param>
        /// <returns>
        /// A new <see cref="Color"/> value.
        /// </returns>
        protected Color LightenColor(Color original, int value, int opacity)
        {
            Color returnValue;

            returnValue = Color.FromArgb(opacity, LightenValue(original.R, value),
                                              LightenValue(original.G, value),
                                              LightenValue(original.B, value));

            return returnValue;
        }
        #endregion
    }
}
